/**
 * @fileoverview Giant Interective Group, Inc. Javascript Library v2.0.1.
 * 该Javascript UI库是基于jQuery的扩展。
 * <pre>
 * Copyright (C) 2004-2009 Giant Interective Group, Inc. All rights reserved.
 * 版权所有 2004-2009 上海巨人网络科技有限公司
 * </pre>
 *
 * @version #version, #date
 * @author  Fuchun
 */

if(typeof giant === 'undefined')
    var giant = window.giant = {};
if (typeof giant.ui === 'undefined')
    giant.ui = {};
(function($) {

var $dom = giant.dom, isIE6 = (B.msie && B.version < 7);
var defaultButtonPrefix = 'gbtn_'; // 默认的按钮Id前缀。
var reButtons = {}; // 按钮的缓存
var $G = giant, $UI = giant.ui;

giant.extend(giant.ui,
/** @lends giant.ui */
{
    /**
     * 控件自动组装默认的Id起始号。
     * @type Number
     */
    AUTO_START_ID: 10000,
    /**
     * 暗黑色背景默认的容器Id。
     * @type String
     */
    DEFAULT_GLOOMY_ID: 'giant_gloomy',
    /**
     * 让浏览器视窗可见的Document全部范围变暗，即不能点击到Document的任何一个地方。
     * @example
     * <pre>
     *
     * </pre>
     * @param {Function} callback 暗黑背景出现后执行的回调函数。
     * @param {Array} args 回函数的参数集合。
     * @param {Boolean} bindWindow 指示是否绑定窗口的<code>resize</code>事件。
     */
    buildGloomyBackground: function(callback, args, bindWindow) {
        var gloomy = E(this.DEFAULT_GLOOMY_ID), gloomyIframe;
        if(gloomy == null) {
            gloomy = document.createElement('div');
            gloomy['id'] = this.DEFAULT_GLOOMY_ID;
            gloomy['className'] = 'ui-gloomy';
            if(isIE6) { // IE6
                gloomyIframe = document.createElement('iframe');
                gloomyIframe['id'] = gloomy['id'] + '_iframe';
                gloomy.appendChild(gloomyIframe);
            }
            document.body.appendChild(gloomy);
        }
        gloomy = gloomy == null ? E(this.DEFAULT_GLOOMY_ID) : gloomy;
        var winsize = [$dom.documentWidth(), $dom.documentHeight()];
        //if($(gloomy).width() != winsize[0] && $(gloomy).height() != winsize[1]) {
        $(gloomy).css({ width: winsize[0] + 'px', height: winsize[1] + 'px' });
        if(isIE6) {
            $('#' + gloomy['id'] + '_iframe').css({
                width: winsize[0] + 'px', height: winsize[1] + 'px'
            });
        }
        //}
        $dom.block(gloomy);
        if(giant.isBool(args)) {
            bindWindow = args;
            args = [];
        }
        args = args || [];
        bindWindow = typeof bindWindow === 'undefined' ? true :
                (typeof bindWindow !== 'boolean') ? true : bindWindow;
        if(bindWindow) {
            $(window).resize(function() {
                if($(gloomy).css('display') != 'none')
                    giant.ui.buildGloomyBackground(callback, args, bindWindow);
            });
        }
        if(giant.isFunction(callback))
            callback.apply(gloomy, args);
    },

    /**
     * 移除(隐藏)暗黑色背景。
     */
    removeGloomyBackground: function() {
        var gloomy = E(this.DEFAULT_GLOOMY_ID);
        if(gloomy == null) {
            return;
        } else {
            gloomy.style.display = 'none';
        }
    },
    /**
     * 若pos指定的位置不为null，则定位到指定的位置。否则定位至浏览器视窗的中间。
     *
     * @param {Element} o 要进行定位的Html元素。
     * @param {Array} pos 指定的位置
     * @param {Function} callback 定位后回调的函数。
     * @param {Array} args 回调函数的参数。
     */
    location: function(o, pos, callback, args) {
        if(giant.isFunction(pos)) {
            callback = pos;
            pos = [];
            args = [];
        }
        var w = parseInt(o.offsetWidth || $(o).css('width'));
        var cs = [$dom.clientWidth(), $dom.clientHeight()];
        var ss = [$dom.scrollLeft(), $dom.scrollTop()];
        if(giant.isUndef(pos) || (giant.isArray(pos) && pos.length == 0))
            pos = [(((cs[0] + ss[0]) / 2) - (w / 2)), ss[1] + 150];
        $dom.xy(o, pos, callback, args);
    },
    /**
     * giant.ui 组件事件列表。
     * @type Array
     */
    events: [
        'click', 'mouseover', 'mouseout', 'mousemove', 'focus', 'blur',
        'dblclick', 'keypress', 'keyup', 'keydown'
    ],

    /**
     * 弹出框主样式类集合。
     * @example
     * <pre>
     * giant.ui.popupTemplates['confirm'] - 信息确认框
     * giant.ui.popupTemplates['msgbox'] - 消息框
     * giant.ui.popupTemplates['dialog'] - 对话框
     * giant.ui.popupTemplates['prompt'] - 信息输入框
     * </pre>
     * @type Object
     */
    popupTemplates: {
        'confirm': 'ui-confirm',
        'msgbox': 'ui-msgbox',
        'dialog': 'ui-dialog',
        'prompt': 'ui-prompt'
    },

    /**
     * 根据配置生成相应的弹出框模板。
     * @param {Object} configs 弹出框模板配置。
     * @returns {String} 弹出框模板Html代码字符串。
     */
    getPopupTemplate: function(configs) {
        var b = new StringBuilder();
        b.append('<div id="').append(configs.id).append('" class="ui-popup-warpper" ');
        b.append('style="width:').append(configs.width).append('px;display:none;">\n');
        b.append('<table cellpadding="0" border="0" class="wp100">');
        b.append('<tbody>\n<tr>\n');
        b.append('  <td class="top-left"></td><td class="top"></td><td class="top-right"></td>');
        b.append('</tr>\n');
        b.append('<tr>\n');
        b.append('  <td class="middle-left"></td>\n');
        b.append('  <td class="middle">\n');
        b.append('    <div class="ui-popup-title"><h2>').append(configs.title).append('</h2>');
        b.append('      <a class="ui-popup-close" href="javascript:void(0);" id="')
            .append(configs.btnCloseId).append('"></a>\n');
        b.append('    </div>');
        b.append('    <div class="ui-popup-content" id="').append(configs.contentId).append('">\n');
        b.append(getPopupContentTemplate(configs.contentTemp, configs.content));
        b.append('    </div>\n');

        switch(configs.template) {
            case 'confirm':
                b.append('    <div class="ui-popup-ext">\n');
                b.append('      <input type="button" id="').append(configs.btnConfirmId).append('" value="');
                b.append(configs.confirm.text).append('" class="').append(configs.confirm.cssClass).append('" />&nbsp;&nbsp;\n');
                b.append('      <input type="button" id="').append(configs.btnCancelId).append('" value="');
                b.append(configs.cancel.text).append('" class="').append(configs.cancel.cssClass).append('" />');
                b.append('    </div>\n');
                break;
            case 'msgbox':
                b.append('    <div class="ui-popup-ext">\n');
                b.append('      <input type="button" id="').append(configs.confirm.id).append('" value="');
                b.append(configs.confirm.text).append('" class="').append(configs.confirm.cssClass).append('" />&nbsp;&nbsp;\n');
                b.append('    </div>\n');
                break;
        }
        b.append('  </td>\n');
        b.append('  <td class="middle-right"></td>');
        b.append('</tr>\n');
        b.append('<tr>\n');
        b.append('<td class="bottom-left"></td><td class="bottom"></td><td class="bottom-right"></td>');
        b.append('</tr>\n');
        b.append('</tbody>');
        b.append('</table>');
        b.append('</div>\n');
        return b.toString();
    }
});

window.getPopupContentTemplate = function(template, content) {
	switch(template) {
        case 'confirm':
        case 'msgbox':
            return '<div class="msg-box"><div class="ico-b-caution">' +
                    (content || '') + '</div></div>';
        default:
            return (content || '');
    }
};

/**
 * 创建一个新的按钮控件。
 * @class giant.ui.JButton。Giant UI 的JButton控件。
 * @example
 * <pre><span class="annotate">
 * // <strong class="btitle">etc.1 :</strong>
 * // 将按钮放在 &lt;div id="div1"&gt;&lt;/div&gt; 中</span>
 * var btnConfirm = new giant.ui.JButton({
 *     container: '#div1', <span class="annotate">// 必须指定按钮控件的容器</span>
 *     text: '重新来一次',
 *     click: function(e) { alert(e.type + ': ' + this.value); },
 *     mouseover: function(e) { this.style.backgroundColor = '#ff0000'; },
 *     mouseout: function(e) { this.style.backgroundColor = '#ffffff'; }
 * });
 * <span class="annotate">// 重新定义并绑定onmouseover事件的函数。</span>
 * btnConfirm.bind('mouseover', {bgcolor:'#ffffe0'}, function(e) {
 *     this.style.backgroundColor = e.data.bgcolor;
 * });
 * <span class="annotate">// 生成的JButton HTML为(Id属性的序号不一定为10001)：
 * // &lt;div id="div1"&gt;&lt;input id="gbtn_10001", type="button" value="重新来一次" class="ui-button" /&gt;&lt;/div&gt;
 *
 * // <strong class="btitle">etc.2 :</strong>
 * // HTML中已存在 &lt;input type="button" id="btn_remove" value="移 除" /&gt;</span>
 * var btnRemove = new giant.ui.JButton({
 *     id: 'btn_remove', <span class="annotate">// 绑定Id为 btn_remove 的按钮</span>
 *     cssClass: 'btnmain',
 *     click: function(e) {
 *         // click coding
 *     }
 * });
 * <span class="annotate">
 * // 初始化之后，JButton HTML为 :
 * // &lt;input type="button" id="btn_remove" value="移 除" class="btnmain" /&gt;
 * // 并绑定了click事件</span>
 * <strong class="btitle">按钮控件中可以绑定的事件：</strong>
 * click、mouseover、mouseout、mousemove、dblclick、keypress、kepup、keydown。
 * </pre>
 * @constructor
 * @param {Object} configs 按钮的属性集。
 */
giant.ui.JButton = function(configs) {
    var options = {container: '', text: '', cssClass: ''};
    configs = giant.extend(options, configs, true);
    if(typeof configs['id'] !== 'undefined')
        this.id = configs['id'];
    //是否使用原始的HTML的JButton控件，默认为true
    this.isOriginal = configs['isOriginal'] || true;
    //按钮是否处于隐藏状态，默认为false
    this.hidden = configs['hidden'] || false;
    //按钮是否处于不可用状态，默认为false
    this.disabled = configs['disabled'] || false;
    //按钮控件的类型属性(只读属性)
    this.type = 'button';
    // 按钮上显示的文字
    this.text = giant.isEmpty(configs['text']) ? '确 定' : configs['text'];
    //按钮上应用的css样式类，默认为 ui-button
    this.cssClass = configs['cssClass'] === '' ? 'ui-button' : configs['cssClass'];
    if(typeof configs['container'] !== 'undefined' && configs['container'] !== '')
        // 按钮的容器
        this.jContainer = $(configs['container']);
    this.initComponent(configs);
};
/**#@+
 * @memberOf giant.ui.JButton
 * @method
 */
giant.ui.JButton.prototype = {
    /** 初始化并生成按钮。
     * @private
     */
    initComponent: function(configs) {
        this.jButton = $('#' + this.id);
        // 未指定按钮的父元素，必须指定按钮Id并且页面中存在这个按钮，否则抛出错误。
        if(giant.isUndef(this.jContainer) || this.jContainer.length === 0) {
            if(!this.id || giant.isUndef(this.jButton) || this.jButton.length === 0) {
                throw new Error('The button id is undefined or not found.');
            }
        } else { // 指定了按钮父元素
            if(giant.isUndef(this.jButton) || this.jButton.length === 0) {
                this.getId();
                var buf = new StringBuilder();
                if(this.isOriginal) {
                    buf.append('<input type="').append(this.type).append('" value="')
                        .append(this.text).append('" ').append('id="').append(this.id)
                        .append('" class="').append(this.cssClass).append('" />');
                    this.jContainer.append(buf.toString());
                    this.jButton = $('#' + this.id);
                }
            }
        }
        var button = this.jButton;
        $.each(giant.ui.events, function(i, name) {
            var data = configs[name + 'data'] || {};
            if(giant.isFunction(configs[name]))
                button.bind(name, data, configs[name]);
        });
        if(this.hidden)
            this.jButton.css('display', 'none');
        if(this.disabled)
            this.jButton.attr('disabled', true);
    },
    /** 启用按钮。*/
    enable: function() {
        if(this.jButton) {
            this.jButton.attr('disabled', false);
        }
    },
    /** 禁用按钮。*/
    disable: function() {
        if(this.jButton) {
            this.jButton.attr('disabled', true);
        }
    },
    /** 显示按钮。*/
    show: function() {
        if(this.jButton) this.jButton.css('display', '');
    },
    /**
     * 绑定此按钮控件的指定事件的处理函数。若指定的事件已存在，则会被新的替换。
     * @param {String} ename 要绑定的事件名称。
     * @param {Object} data 要传递给事件函数的参数集。
     * @param {Function} fn 要绑定的事件函数。
     * @returns {giant.ui.Button} 返回此按钮控件的实例。
     */
    bind: function(ename, data, fn) {
        if(this.jButton) {
            if(!ename) return;
            this.jButton.unbind(ename);
            this.jButton.bind(ename, data || {}, fn || giant.EmptyFn);
        }
        return this;
    },
    /**
     * 移除指定的事件绑定。
     * @param {String|Array} ename 要移除的指定事件。
     * @returns {giant.ui.Button} 返回此按钮控件的实例。
     */
    unbind: function(ename) {
        if(this.jButton) {
            if(giant.isUndef(ename)) {
                this.jButton.unbind();
            } else if(giant.isString(ename)) {
                this.jButton.unbind(ename);
            } else if(giant.isArray(ename)) {
                $.each(ename, function(i, name) {
                    this.jButton.unbind(name);
                });
            }
        }
        return this;
    },
    /**
     * 设置按钮的显示的文本值。
     * @param {String} text 按钮的文本值。
     */
    setText: function(text) {
        if(this.jButton)
            this.jButton.attr('value', text);
    },
    /**
     * 给按钮添加样式类。
     * @param {String} className 要添加的按钮样式类。
     * @returns {giant.ui.Button} 返回此按钮控件的实例。
     */
    addClass: function(className) {
        if(this.jButton)
            this.jButton.addClass(className);
        return this;
    },
    /**
     * 移除按钮中的样式类。
     * @param {String} className 要移除的按钮样式类。
     * @returns {giant.ui.Button} 返回此控件实例。
     */
    removeClass: function(className) {
        if(this.jButton)
            this.jButton.removeClass(className);
        return this;
    },
    /**
     * 返回此按钮的Id。
     * @returns {String} 此按钮的Id。
     */
    getId: function() {
        return this.id || (this.id = defaultButtonPrefix + (++$UI.AUTO_START_ID));
    }
};
/**#@-*/

var cmbSettings = {
    container: '',
    id: '#cmb_select',
    name: 'selectProperty',
    cssClass: ''
};

/**
 * 新建一个 giant.ui.ComboBox 下拉列表框控件实例。
 * @class giant.ui.ComboBox 下拉列表框控件。
 * @example
 * <pre><span class="annotate">
 * <strong>此类的快捷方式为：var cmb = $.combobox(Options参数);</strong>
 * // 以下例子展示了 giant.ui.ComboBox 控件的用法
 * // 假设当前页面有一个Id为 cmb_astro 的下拉框控件 &lt;select id=&quot;cmb_astro&quot;&gt;&lt;/select&gt;</span>
 * var cmbAstro = new giant.ui.ComboBox({
 *     id: 'cmb_astro',
 *     name: 'user.astro',
 *     cssClass: 'w100',
 *     change: function() {
 *         <span class="annotate">// this, 表示控件元素对象
 *         // 这是要绑定的 onchange 事件<strong>（可选）</strong></span>
 *     }
 * });
 * <span class="annotate">// 你也可以根据需要<strong>进行后期绑定</strong></span>
 * cmbAstro.addEvent("change", function() {
 *     <span class="annotate">// onchange 事件代码</span>
 * });
 * <span class="annotate">// 在不需要的时候，<strong>取消事件的绑定</strong></span>
 * cmbAstro.removeEvent("change");
 * <span class="annotate"><strong>// 具体的添加选项，移除选项，添加选项组等操作，见具体的方法。</strong></span>
 * </pre>
 *
 * @constructor
 * @param {Object} options ComboBox的控件属性。
 * @returns {giant.ui.ComboBox} 下拉列表框控件
 */
giant.ui.ComboBox = function(options) {
    this.initComponent(options);
};

/**#@+
 * @memberOf giant.ui.ComboBox
 * @method
 */
giant.ui.ComboBox.prototype = {

    // 初始化ComboBox
    initComponent: function(options) {
        var s = giant.extend(cmbSettings, options, true);
        this.jComboBox = s.id.startsWith('#') ? $(s.id) : $('#' + s.id);
        if(this.jComboBox.length === 0) {
            if(s.container === '')
                throw new Error('new giant.ui.ComboBox is not direct container. ' + s.id + ' is not found.');
            else {
                this.jComboBox = $('<select id="' + s.id +'" name="' + s.name + '"></select>');
                this.jComboBox.appendTo(s.container);
            }
            if(s.cssClass !== '')
                this.jComboBox.addClass(s.cssClass);
       }
       this.comboBox = this.jComboBox[0];
       for(var i = 0, len = this.comboBox.length; i < len; i++) {
           if(giant.isFunction(s[giant.ui.events[i]]))
               this.addEvent(giant.ui.events[i], s[giant.ui.events[i]]);
       }
       return this;
    },

    /**
     * 返回此ComboBox当前选项的值。
     * @returns {String} 此ComboBox当前选项的值。
     */
    value: function() {
        if(this.jComboBox != null && this.jComboBox.length >0)
            return this.jComboBox.val();
        return '';
    },

    /**
     * 为此ComboBox添加HTMLOptGroupElement元素。
     *
     * @param {Object} o HTMLOptGroupElement的属性集合。<br>
     *         o.id    --&gt;  要添加的OptGroup元素的Id   <br>
     *         o.label --&gt;  要添加的OptGroup元素的label属性
     * @returns {HTMLOptGroupElement} 新添加的HTMLOptGroupElement元素。
     */
    addGroup: function(o) {
        if(this.comboBox != null) {
            if(this.comboBox.tagName &&
                    this.comboBox.tagName.toLowerCase() == 'select') {
                var $self = this;
                var optg = $('<optgroup></optgroup>');
                optg.attr('label', o['label']);
                if(o.id)
                    optg.attr('id', o.id);
                optg.appendTo(this.jComboBox);
                return optg[0];
            }
        }
        return false;
    },

    /**
     * 为此ComboBox控件添加选项。
     * @example
     * <pre>
     * var cmb = new giant.ui.ComboBox({id:'cmb_city'});
     * <span class="annotate"><strong>// 添加选项的几种方法：</strong>
     * // 数组方式添加：</span>
     * cmb.addItem([ {text:"上海市", value:"310000"}, {text:"北京市", value:"110000"} ]);
     * cmb.addItem([ "上海市", "北京市", "天津市" ]);
     * <span class="annotate">// 键/值对方式添加：</span>
     * cmb.addItem({text:"上海市", value:"310000"});
     * <span class="annotate">// 字符串方式添加(文本和值相同)：</span>
     * cmb.addItem("上海市");
     * </pre>
     *
     * @param {String|Array|Object} o 要添加的选项信息。
     * @param {HTMLOptGroupElement} group 若指定了此选项，则选项将添加到该选项组下<strong>（可选）</strong>。
     * @param {Function} callback 完成添加选项的操作后执行的回调函数<strong>（可选）</strong>。
     */
    addItem: function(o, group, callback) {
        if(giant.isFunction(group)) {
            callback = group;
            group = null;
        }
        var i;
        var buf = new StringBuilder();
        if(giant.isArray(o)) {
            for(i in o) {
                if(giant.isString(o[i])) {
                    buf.append('<option value="').append(o[i]).append('">');
                    buf.append(o[i]).append('</option>');
                } else if(o[i].text && !o[i].text.isEmpty() && o[i].value) {
                    buf.append('<option value="').append(o[i].value).append('">');
                    buf.append(o[i].text).append('</option>');
                }
            }
        } else if(o.text && !o.text.isEmpty() && o.value) {
            buf.append('<option value="').append(o.value).append('">');
            buf.append(o.text).append('</option>');
        } else if(giant.isString(o)) {
            buf.append('<option value="').append(o).append('">');
            buf.append(o).append('</option>');
        }
        if(group == null) {
            this.jComboBox.append(buf.toString());
            if(giant.isFunction(callback))
                callback.call(this.jComboBox[0]);
        } else {
            group.append(buf.toString());
            if(giant.isFunction(callback))
                callback.call(group[0]);
        }
    },

    /**
     * 移除指定条件的控件选项。
     * @example
     * <pre>
     * var cmb = new giant.ui.ComboBox({id:'cmb_city'});
     * <span class="annotate"><strong>// 移除选项的几种方法：</strong>
     * // 文本方式移除：</span>
     * cmb.remove({text:"上海市"});
     * <span class="annotate">// 值方式移除：</span>
     * cmb.remove({value: "310000"});
     * <span class="annotate">// 文本和值方式移除：</span>
     * cmb.remove({text:"上海市", value:"310000"});
     * <span class="annotate">// 索引方式移除(索引的大小在选项长度区间内)：</span>
     * cmb.remove(5);
     * </pre>
     *
     * @param {Object} o 要移除选项的条件。
     * @param {Function} callback 移除选项后执行的回调函数。
     */
    remove: function(o, callback) {
        if(giant.isFunction(o)) {
            callback = o;
            o = null;
        }
        var len = this.jComboBox[0].length, i;
        if(o == null) {
            this.jComboBox[0].length = 0;
        } else if(giant.isString(o)) {
            for(i = 0; i < len; i++) {
                if(this.comboBox.options[i].text === o || this.comboBox.options[i].value === o)
                    this.comboBox.remove(i);
            }
        } else if(giant.isNumber(o)) {
            if(o >= 0 && o < len)
                this.comboBox.remove(o);
        } else if(o.text && !o.value) {
            for(i = 0; i < len; i++) {
                if(this.comboBox.options[i].text == o.text)
                    this.comboBox.remove(i);
            }
        } else if(o.value && !o.text) {
            for(i = 0; i < len; i++) {
                if(this.comboBox.options[i].value == o.value)
                    this.comboBox.remove(i);
            }
        } else {
            for(i = 0; i < len; i++) {
                if(this.comboBox.options[i].value == o.value &&
                        this.comboBox.options[i].text == o.text)
                    this.comboBox.remove(i);
            }
        }
        if(giant.isFunction(callback))
            callback.call(this.comboBox);
    },

    /**
     * 自动选中给定条件的选项，若附合的选项有多个，则选中第一个。
     *
     * @param {Object} o 给定的条件。
     * @param {Function} callback 选中选项后执行的回调函数。
     */
    select: function(o, callback) {
        var $self = this;
        var len = this.comboBox.length, i = 0, sj, si;
        var parseSelected = function(cmb, index) {
            if(isIE6)
                setTimeout(function() {
                    cmb.options[index].selected = true;
                }, 10);
            else
                cmb.options[index].selected = true;
            sj = index;
            si = {
                text: cmb.options[index].text,
                value: cmb.options[index].value
            };
        };
        if(giant.isString(o) || giant.isNumber(o)) {
            for(i = len; --i >= 0;) {
                if(this.comboBox.options[i].value == o ||
                        this.comboBox.options[i].text == o) {
                    parseSelected(this.comboBox, i);
                    break;
                }
            }
        } else if(o.text && !o.value) {
            for(i = len; --i >= 0;) {
                if(this.comboBox.options[i].text == o.text) {
                    parseSelected(this.comboBox, i);
                    break;
                }
            }
        } else if(!o.text && o.value) {
            for(i = len; --i >= 0;) {
                if(this.comboBox.options[i].value == o.value) {
                    parseSelected(this.comboBox, i);
                    break;
                }
            }
        } else {
            for(i = len; --i >= 0;) {
                if(this.comboBox.options[i].text == o.text &&
                        this.comboBox.options[i].value == o.value) {
                    parseSelected(this.comboBox, i);
                    break;
                }
            }
        }
        if(giant.isFunction(callback)) {
            callback.apply(this.comboBox, [sj, si]);
        }
    },

    /**
     * 获取该ComboBox的选项个数。
     * @returns {Number} 该ComboBox的选项个数。
     */
    length: function() {
        return this.comboBox.length ? this.comboBox.length : 0;
    },

    /**
     * 获取该ComboBox表示的jQuery对象。
     *
     * @returns {jQuery} 该ComboBox表示的jQuery对象。
     */
    getJComboBox: function() {
        return this.jComboBox;
    },

    /**
     * 获取该ComboBox表示的HTMLSelectElement控件元素对象。
     *
     * @returns {HTMLSelectElement} HTMLSelectElement控件元素对象。
     */
    getComboBox: function() {
        return this.comboBox;
    },

    /**
     * 给该ComboBox控件添加并绑定事件。若事件已被绑定，则用新的覆盖旧的。
     *
     * @param {String} eName 要绑定的事件的名称。
     * @param {Function} eFunction 要绑定的事件。
     */
    addEvent: function(eName, eFunction) {
        this.jComboBox.bind(eName, eFunction);
    },

    /**
     * 移除此ComboBox控件的事件。
     *
     * @param {String} eName 要移除的事件。
     */
    removeEvent: function(eName) {
        this.jComboBox.unbind(eName);
    }
};
/**#@-*/
var comboBoxesCache = {};
$.combobox = function(options) {
    if(giant.isUndef(comboBoxesCache[options.id]))
        comboBoxesCache[options.id] = new giant.ui.ComboBox(options);
    return comboBoxesCache[options.id].initComponent(options);
};

// Confirm 确认消息框的默认选项
var cofirmOptions = {
    title: '【系统确认信息】',
    content: '',
    confirm: {
        text: '确 定',
        cssClass: 'btn-small btn-01',
        click: giant.EmptyFn
    },
    cancel: {
        text: '取 消',
        cssClass: 'btn-small btn-02',
        click: giant.EmptyFn
    },
    width: 300,
    gloomy: true,
    system: false
};

// Confirm 确认消息框的惟一实例。
var confirmInstance = null;

/**
 * 创建一个新的确认消息框。
 * @class 确认消息框。是否使用系统的确认消息框取决于参数的配置。
 * @constructor
 * @param {Object} configs 确认消息框的参数配置。
 */
giant.ui.Confirm = function(configs) {
    this.initComponent(cofirmOptions, configs);
};

/**#@+
 * @memberOf giant.ui.Confirm
 * @method
 */
giant.ui.Confirm.prototype = {
    /**
     * 初始化并生成确认消息框。
     * @private
     */
    initComponent: function(options, configs) {
        configs = this._initParams(options, configs);
        if(configs.system) {
            var result = confirm(configs.content);
            if(result) {
                configs.confirm.click.apply(this, configs.confirm.args);
            } else {
                configs.cancel.click.apply(this, configs.cancel.args);
            }
        } else {
        	if(giant.isFunction(configs.before))
        	    configs.before.call(this, configs);
            this._generateConfirm(configs);
        }
    },
    // 初始化参数数据
    _initParams: function(options, configs) {
        configs.system = $G.isUndef(configs.system) ? false : configs.system;
        configs = $G.extend(options, configs, true);
        var ccf = configs.confirm, ccl = configs.cancel, dccf = options.confirm, dccl = options.cancel;
        configs.content = $G.isNullOrEmpty(configs.content) ? String.Empty : configs.content.trim();
        configs.system = $G.isBool(configs.system) ? configs.system : options.system;
        configs.title = $G.isNullOrEmpty(configs.title) ? options.title : configs.title.trim();
        configs.gloomy = $G.isBool(configs.gloomy) ? configs.gloomy : options.gloomy;
        if(ccf != null && ccl != null) {
            if(!configs.system) {
                ccf.text = $G.isNullOrEmpty(ccf.text) ? dccf.text : ccf.text;
                ccl.text = $G.isNullOrEmpty(ccl.text) ? dccl.text : ccl.text;
                ccf.cssClass =  $G.isNullOrEmpty(ccf.cssClass) ? dccf.cssClass : ccf.cssClass;
                ccl.cssClass = $G.isNullOrEmpty(ccl.cssClass) ? dccl.cssClass : ccl.cssClass;
            }
            ccf.click = !$G.isFunction(ccf.click) ? giant.EmptyFn : ccf.click;
            ccl.click = !$G.isFunction(ccl.click) ? giant.EmptyFn : ccl.click;
            ccf.args = ccf.args || [];
            ccl.args = ccl.args || [];
        }
        if(!configs.system) { // 不使用默认的系统确认消息框
            this.id = 'gui_cfm';
            this._btnCfmId = this._btnCfmId || 'btn_cfm_' + this.id; // 确认按钮Id
            this._btnCclId = this._btnCclId || 'btn_ccl_' + this.id; // 取消按钮Id
            this._btnClsId = this._btnClsId || 'btn_cls_' + this.id; // 关闭按钮Id
            this._contentId = this._contentId || this.id + '_content'; // 确认信息内容容器Id
            // 消息框的宽度 单位：px
            this._width = giant.isNumber(configs.width) ? configs.width : options.width;
            this.jConfirm = null;
        }
        return configs;
    },
    // 显示确认信息框
    _show: function(gloomy) {
        if(this.jConfirm != null && this.jConfirm.length > 0) {
            if(gloomy)
                $UI.buildGloomyBackground();
            var $self = this, maxIndex = 9000;
            $('.ui-popup').each(function(i) {
                var zIndex = $(this).css('zIndex'), display = $(this).css('display');
                if(display !== 'none') {
                    if(zIndex >= maxIndex)
                        maxIndex = zIndex;
                }
            });
            this.jConfirm.css({'zIndex':++maxIndex, 'display':'block'});
            $UI.location(this.jConfirm);
        }
    },
    // 绑定按钮事件
    _bindEvents: function(configs) {
        var $self = this;
        $('#' + this._btnCfmId).click(function() {
            $self.jConfirm.hide('fast');
            var cfm = configs.confirm.click.call(this, $self);
            cfm = giant.isBool(cfm) ? cfm : true;
            if(cfm) $UI.removeGloomyBackground();
        });
        $('#' + this._btnCclId).click(function() {
            $self.jConfirm.hide('fast');
            var ccl = configs.cancel.click.call(this, $self);
            ccl = giant.isBool(ccl) ? ccl : true;
            if(ccl) $UI.removeGloomyBackground();
        });
        $('#' + this._btnClsId).click(function() {
            $('#' + $self._btnCclId).click();
        });
    },
    // 生成确认消息框
    _generateConfirm: function(configs) {
        var $self = this;
        this.jConfirm = $('#'.concat(this.id));
        if(this.jConfirm.length === 0) {
            var sTemplate = $UI.getPopupTemplate({
                template: 'confirm',
                contentTemp: configs.contentTemp || 'confirm',
                id: $self.id,
                width: $self._width,
                title: configs.title,
                contentId: $self._contentId,
                content: configs.content || '',
                btnCloseId: $self._btnClsId,
                btnConfirmId: $self._btnCfmId,
                btnCancelId: $self._btnCclId,
                confirm: {
                    text: configs.confirm.text,
                    cssClass: configs.confirm.cssClass
                },
                cancel: {
                    text: configs.cancel.text,
                    cssClass: configs.cancel.cssClass
                }
            });
            this.jConfirm = $(sTemplate).appendTo('body');
        } else {
            $('#' + this._contentId).html(getPopupContentTemplate(configs.contentTemp || 'confirm', configs.content));
            $("#" + this.id +" .ui-popup-title h2").text(configs.title);
            $('#' + this.id).css("width", configs.width+"px");
            $('#' + this._btnCfmId).attr('value', configs.confirm.text).unbind();
            $('#' + this._btnCclId).attr('value', configs.cancel.text).unbind();
            $('#' + this._btnClsId).unbind();
        }
        this._bindEvents(configs);
        this._show(configs.gloomy);
    }
};
/**#@-*/

$.confirm = function(configs) {
    if(confirmInstance == null)
        confirmInstance = new giant.ui.Confirm(configs);
    else
        confirmInstance.initComponent(cofirmOptions, configs);
    return confirmInstance;
};

// giant.ui.MsgBox的唯一实例
var msgboxInstance = null;
var msgboxOptions = {
    title: '【系统消息】',
    message: '',
    before: giant.EmptyFn,
    confirm: {
        id: 'btn_msgbox_cfm',
        text: '确 定',
        cssClass: 'btn-small btn-01',
        click: giant.EmptyFn
    },
    closeEvent: null,
    gloomy: true,
    width: 300
};

/**
 * 创建一个新的消息框。
 * @class 消息框。是否使用系统的消息框取决于参数的配置。
 * @example
 * <pre>
 * var msgParams = {
 *     message: '要显示的消息内容',
 *     before: function() {
 *         alert('消息框弹出之前执行的函数。');
 *     },
 *     confirm: {
 *         text: '确 认',  <span class="annotate">// 确认按钮的文字 (可选)</span>
 *         cssClass: 'ui-button', <span class="annotate">// 确认按钮的样式类 (可选)</span>
 *         <span class="annotate">// 确认按钮的点击事件函数 (可选)</span>
 *         click: function() {
 *             <span class="annotate">// this 表示该确空按钮对象</span>
 *             alert('点击确认按钮执行的函数。');
 *         }
 *     },
 *     after: function() {
 *         alert('消息框关闭后执行的函数。');
 *     }
 * };
 * giant.ui.MsgBox.get(msgParams);
 * <span class="annotate">// 另一种便捷的调用方法：</span>
 * <strong>$.msgbox(msgParams);</strong>
 * </pre>
 * @constructor
 * @param {Object} configs 确认消息框的参数配置。 <br/>
 *         configs.title    --&gt;&gt;  消息框标题。默认为 <strong>【系统消息】</strong> <br/>
 *         configs.message  --&gt;&gt;  消息框消息内容 <br/>
 *         configs.before   --&gt;&gt;  消息框弹出前执行的回调函数。默认为 <strong>空函数</strong><br/>
 *         configs.after    --&gt;&gt;  消息框关闭后执行的回调函数。默认为 <strong>空函数</strong><br/>
 *         configs.confirm  --&gt;&gt;  消息框的确认按钮配置 <br/>
 *         configs.confirm.id --&gt;&gt;  消息框确认按钮Id。默认为 <strong>btn_msgbox_cfm</strong><br/>
 *         configs.confirm.text --&gt;&gt;  消息框确认按钮的文字。默认为 <strong>确 定</strong><br/>
 *         configs.confirm.cssClass --&gt;&gt;  消息框确认按钮的Css样式类。默认为 <strong>ui-button</strong><br/>
 *         configs.confirm.click  --&gt;&gt;  消息框确认按钮的Click事件函数。。默认为 <strong>空函数</strong>
 */
giant.ui.MsgBox = function(configs) {
    this.initComponent(configs);
};
/**#@+
 * @memberOf giant.ui.MsgBox
 * @method
 */
giant.ui.MsgBox.prototype = {
    /**
     * 初始化消息框组件。
     * @private
     */
    initComponent: function(configs) {
        this.id = 'gui_msgbox';
        this.messageId = this.id + '_message';
        this.message = configs.message;
        this.btnCloseId = this.id + '_cls';
        configs = giant.extend(msgboxOptions, configs || {}, true);
        this._generateMsgBox(configs);
    },
    // 显示消息框
    _show: function(gloomy) {
        if(this.jMsgBox != null && this.jMsgBox.length > 0) {
            if(gloomy)
                $UI.buildGloomyBackground();
            var $self = this, maxIndex = 9000;
            $('.ui-popup').each(function(i) {
                var zIndex = $(this).css('zIndex'), display = $(this).css('display');
                if(display !== 'none') {
                    if(zIndex >= maxIndex)
                        maxIndex = zIndex;
                }
            });
            this.jMsgBox.css({'zIndex':++maxIndex, 'display':'block'});
            $UI.location(this.jMsgBox);
        }
    },

    // 绑定组件中的控件事件
    _bindEvents: function(configs) {
        var $self = this;
        if(giant.isFunction(configs.before))
            configs.before.call($self);
        $('#' + configs.confirm.id).click(function() {
            $self.jMsgBox.hide('fast');
            // this 表示确认按钮对象
            var cfm = configs.confirm.click.call(this, $self);
            cfm = giant.isBool(cfm) ? cfm : true;
            if(cfm) $UI.removeGloomyBackground();
            if(giant.isFunction(configs.after))
                configs.after.call($self);
        });
        $('#' + this.btnCloseId).click(function() {
            if (giant.isFunction(configs.closeEvent)) {
                $self.jMsgBox.hide('fast');
                var cfm = configs.closeEvent.call(this, $self);
                cfm = giant.isBool(cfm) ? cfm : true;
                if (cfm) $UI.removeGloomyBackground();
                if (giant.isFunction(configs.after))
                    configs.after.call($self);
            }else{
                 $('#' + configs.confirm.id).click();
            }
        });
    },
    // 生成MsgBox信息框组件Html
    _generateMsgBox: function(configs) {
        var $self = this;
        this.jMsgBox = $('#' + this.id);
        if(this.jMsgBox.length == 0) {
            var sMsgBox = $UI.getPopupTemplate({
                id: $self.id,
                title: configs.title,
                template: 'msgbox',
                contentTemp: configs.contentTemp || 'msgbox',
                contentId: $self.messageId,
                content: $self.message,
                btnCloseId: $self.btnCloseId,
                confirm: configs.confirm,
                width: configs.width
            });
            this.jMsgBox = $(sMsgBox).appendTo('body');
        } else {
            $('#' + this.messageId).html(getPopupContentTemplate(configs.contentTemp || 'msgbox', configs.message));
            $('#' + this.id + " .ui-popup-title h2").html(configs.title);
            $('#' + this.id).css("width", configs.width+"px");
            $('#' + configs.confirm.id).unbind();
            $('#' + this.btnCloseId).unbind();
        }
        this._bindEvents(configs);
        this._show(configs.gloomy);
    }
};
/**#@- */

$.msgbox = function(configs) {
    if(msgboxInstance == null)
        msgboxInstance = new giant.ui.MsgBox(configs);
    else
        msgboxInstance.initComponent(configs);
    return msgboxInstance;
};

// dialog默认的参数数据
var dialogOptions = {
    title: '【系统对话框】',
    before: giant.EmptyFn,
    close: giant.EmptyFn,
    error: giant.EmptyFn,
    content:"",
    isAjax:false,
    isChange:false,
    page: {
        url: '',
        params: {},
        success: giant.EmptyFn
    },
    width: 300
}, dialogInstances = {};

/**
 * 创建一个新的对话框。
 * @class giant.ui.Dialog 对话框，网页弹出层。
 * @constructor
 * @param {Object} configs 对话框的参数配置。
 */
giant.ui.Dialog = function(configs) {
	configs = giant.extend(dialogOptions, configs, true);
    this.id = 'gui_dialog_' + (configs.index || 'default');
    this.initComponent(configs);
};
giant.ui.Dialog.autoId=100;
/**#@+
 * @memberOf giant.ui.Dialog
 * @method
 * @example
 * <pre>
 * var dia2 = new giant.ui.Dialog({
 *           isAjax:true,
 *          page: {
 *              url: 'test.html',
 *              params: {},
 *              success: function(){
 *              }
 *          }
 *      });
 * </pre>
 */
giant.ui.Dialog.prototype = {
    /**
     * 初始化对话框。
     * @private
     */
    initComponent: function(configs) {
        this.btnCloseId = this.id + '_close';
        this.contentId = this.id + '_content';
        this.jDialog = $('#' + this.id);
        this._generateDialog(configs);
        this.show();
    },
    /**
     * 显示该对话框。
     */
    show: function() {
        $UI.buildGloomyBackground();
        this.jDialog.css('display', 'block');
        $UI.location(this.jDialog);
    },

    /**
     * 关闭该对话框。
     */
    close: function() {
        $('#' + this.btnCloseId).click();
    },
    
    /**
     * 从页面中移除对话框的Html代码(全部)。
     */
    remove: function() {
    	var index = this.id.replace(/gui_dialog_/ig, '');
    	dialogInstances[index] = undefined;
    	$('#' + this.btnCloseId).unbind();
    	$('#' + this.id).unbind().remove();
    	
    },
    // 绑定事件
    _bindEvents: function(configs) {
        var $self = this;
        $('#' + this.btnCloseId).click(function() {
            $self.jDialog.hide('fast');
            $UI.removeGloomyBackground();
            if(giant.isFunction(configs.close)) {
                configs.close.call($self.jDialog, $('#' + $self.contentId), configs);
            }
        });
    },

    // Ajax请求载入内部页面
    _loadPage: function(configs) {
        var pageParams = configs.page || {}, $self = this;
        if(pageParams.url && pageParams.url !== '') {
            $.ajax({
                type: pageParams.type || 'GET',
                url: pageParams.url,
                data: pageParams.params,
                beforeSend: function() {
                    if(giant.isFunction(configs.before))
                        configs.before.call($self.jDialog, $('#' + $self.contentId), configs);
                    return true;
                },
                complete: function(xhr, status) {
                    if(status === 'success' || status === 'notmodified') {
                        var shtml = xhr.responseText;
                        $('#' + $self.contentId).html(shtml);
                        if(giant.isFunction(pageParams.success))
                            pageParams.success.apply($self, [$self.jDialog, $('#' + $self.contentId), configs]);
                    } else {
                        if(giant.isFunction(configs.error))
                            configs.error.apply($self, [configs]);
                    }
                },
                dataType: pageParams.dataType || 'html'
            });
        }
    },
    // 生成Dialog
    _generateDialog: function(configs) {
        var $self = this;
        if(this.jDialog.length === 0) {
            var sDialog = $UI.getPopupTemplate({
                id: $self.id,
                title: configs.title,
                template: 'dialog',
                btnCloseId: $self.btnCloseId,
                contentId: $self.contentId,
                content: configs.content,
                width: configs.width
            });
            this.jDialog = $(sDialog).appendTo('body');
        } else {
            this.jDialog.find('.ui-popup-title h2').text(configs.title || dialogOptions.title);
            $('#'+this.id).css("width",configs.width+"px");
            $('#' + this.btnCloseId).unbind();
            $('#' + this.contentId).unbind().html('');
        }
        if(configs.isAjax){
            this._loadPage(configs);
        }else{
            $('#' + $self.contentId).html(configs.content);
        }
        this._bindEvents(configs);
    }
};
/**#@- */


$.dialog = function(configs) {
    var index = (configs.index || 'default');
    if(!dialogInstances[index])
        dialogInstances[index] = new giant.ui.Dialog(configs);
    else
        configs.isChange?dialogInstances[index].initComponent(configs):dialogInstances[index].show();
    return dialogInstances[index];
};
/**
 * 图片载入错误时执行的事件函数。
 * @example
 * <pre><span class="annotate">// <strong>快捷调用方式：</strong></span>
 * &lt;img src="女性用户的小头像图片地址" onerror="ImageLoad(this, ImageLoad.HEADPIC_SMALL, 'F');" /&gt;
 * &lt;img src="男性用户的中等头像图片地址" onerror="ImageLoad(this, ImageLoad.HEADPIC_MEDIUM, 'M');" /&gt;
 * &lt;img src="用户上传的图片(大图)地址" onerror="ImageLoad(this, ImageLoad.PHOTO_BIG);" /&gt;
 * <span class="annotate"><strong>类型常量列表：</strong></span>
 * ImageLoad.HEADPIC_SMALL  --&gt;  用户默认小头像(20×20)
 * ImageLoad.HEADPIC_MEDIUM --&gt;  用户默认中等头像(40×40)
 * ImageLoad.HEADPIC_BIG    --&gt;  用户默认小头像(80×80)
 * ImageLoad.PHOTO_SMALL    --&gt;  图片不存在或被删除时的默认显示小图
 * ImageLoad.PHOTO_BIG      --&gt;  图片不存在或被删除时的默认显示大图
 * </pre>
 * 
 * @param {HTMLImageElement|String} o Image图片对象或图片Id。
 * @param {Number} type 默认图片的类型标识。
 * @param {String} gender 用户性别标识(可选参数)。
 * @method
 */
giant.ui.imageLoadError = function(o, type, gender) {
    var target = giant.isString(o) ? $('#' + o) : $(o);
    var imageUrl = Path['images'] + '/images/defaults/';
    switch(parseInt(type)) {
        case 1:
            if(gender == 'M') {
                imageUrl = imageUrl + 'headpic_small_female.jpg';
            } else {
                imageUrl = imageUrl + 'headpic_small_male.jpg';
            }
            break;
        case 2:
            if(gender == 'M') {
                imageUrl = imageUrl + 'headpic_medium_female.jpg';
            } else {
                imageUrl = imageUrl + 'headpic_medium_male.jpg';
            }
            break;
        case 3:
            if(gender == 'M') {
                imageUrl = imageUrl + 'headpic_big_female.jpg';
            } else {
                imageUrl = imageUrl + 'headpic_big_male.jpg';
            }
            break;
        case 4:
            imageUrl = imageUrl + 'default_photo_big.gif';
            break;
        case 5:
            imageUrl = imageUrl + 'default_photo_small.gif';
            break;
        case 6:
            imageUrl = imageUrl + 'group_logo_small.jpg';
            break;
        case 7:
            imageUrl = imageUrl + 'default_app_medium.gif';
            break;
        case 8:
            imageUrl = imageUrl + 'default_app_small.gif';
            break;
    }
    target.attr('src', imageUrl);
};
window.ImageLoad = giant.ui.imageLoadError;
giant.extend(window.ImageLoad, {
    HEADPIC_SMALL: 1,
    HEADPIC_MEDIUM: 2,
    HEADPIC_BIG: 3,
    PHOTO_SMALL: 4,
    PHOTO_BIG: 5,
    GROUP_LOGO_SMALL: 6,
    APP_MEDIUM: 7,
    APP_SMALL: 8
});
})(jQuery);